/*--------------------------------*- C++ -*----------------------------------*\
  =========                 |
  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
   \\    /   O peration     | Website:  https://openfoam.org
    \\  /    A nd           | Version:  dev
     \\/     M anipulation  |
\*---------------------------------------------------------------------------*/
FoamFile
{
    version         2.0;
    format          ascii;
    class           dictionary;
    location        "system";
    object          foamyHexMeshDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //


/*

Control dictionary for foamyHexMesh - automatic mesh generator.

foamyHexMesh phases:
1. fill volume with initial points (initialPoints subdictionary). An option
   is to reread from previous set of points.

2. internal point motion (motionControl subdictionary)

3. every once in a while add point duplets/triplets to conform to
   surfaces and features (surfaceConformation subdictionary)

4. back to 2

5. construct polyMesh.
    - filter (polyMeshFiltering subdictionary)
    - check (meshQualityControls subdictionary) and undo filtering


See also cvControls.H in the conformalVoronoiMesh library

*/


// Important:
// ----------
// Any scalar with a name <name>Coeff specifies a value that will be implemented
// as a faction of the local target cell size
// Any scalar with a name <name>Size specifies an absolute size.


// Geometry. Definition of all surfaces. All surfaces are of class
// searchableSurface.
// Surfaces need to be (almost) closed - use closedTriSurfaceMesh
// if they are not topologically closed. Surfaces need to be oriented so
// the space to be meshed is always on the inside of all surfaces. Use e.g.
// surfaceOrient.
geometry
{
    // Surface to conform to
    flange.obj
    {
        type triSurfaceMesh;
    }

    // Surface used for cell size control
    ref7.stl
    {
        name ref7;
        type triSurfaceMesh;
    }

    refinementBox
    {
        type searchableBox;
    }
}

//Optional: single region surfaces get patch names according to
//          surface only. Multi-region surfaces get patch name
//          surface "_ "region. Default is true
//singleRegionName false;



// Controls for conforming to the surfaces.
surfaceConformation
{
    // A point inside surfaces that is inside mesh.
    locationInMesh (0 0 0);

    // How far apart are point-duplets generated. Balance this between
    // - very low distance: little chance of interference from other
    //   surfaces
    // - largish distance: less non-orthogonality in final cell
    //   (circumcentre far away from centroid)
    pointPairDistanceCoeff      0.1;

    // Mixed feature points - connected to both inside and outside edges.
    // Recreated by inserting triplets of points to recreate a single edge.
    // Done for all edges emanating from point. triplets of points get inserted
    // mixedFeaturePointPPDistanceCoeff distance away from feature point.
    // Set to a negative number to disable.
    mixedFeaturePointPPDistanceCoeff    5.0; //-1;

    // Distance to a feature point within which surface and edge
    // conformation points are excluded - fraction of the local target
    // cell size
    featurePointExclusionDistanceCoeff  0.65;

    // Distance to an existing feature edge conformation location
    // within which other edge conformation location are excluded -
    // fraction of the local target cell size
    featureEdgeExclusionDistanceCoeff   0.65;

    // Optimisation: do not check for surface intersection (of dual edges)
    // for points near to surface.
    surfaceSearchDistanceCoeff  5;

    // Maximum allowable protrusion through the surface before
    // conformation points are added - fraction of the local target
    // cell size. These small protusions are (hopefully) done by mesh filtering
    // instead.
    maxSurfaceProtrusionCoeff   0.1;

    // If feature edge with large angle (so more than 125 degrees) introduce
    // additional points to create two half angled cells (= mitering).
    maxQuadAngle 125;

    // Frequency to redo surface conformation (expensive).
    surfaceConformationRebuildFrequency 10;

    featurePointControls
    {
        specialiseFeaturePoints on;
        guardFeaturePoints      on;
        snapFeaturePoints       on;
        circulateEdges          on;
    }

    // Initial and intermediate controls
    conformationControls
    {
        // We've got a point poking through the surface. Don't do any
        // surface conformation if near feature edge (since feature edge
        // conformation should have priority)

        // distance to search for near feature edges
        edgeSearchDistCoeff         1.1;

        // Proximity to a feature edge where a surface hit is
        //  not created, only the edge conformation is created
        // - fraction of the local target cell size. Coarse
        // conformation, initial protrusion tests.
        surfacePtReplaceDistCoeff   0.5;    // instead of surface point insert
                                            // edge-conformation point

        surfacePtExclusionDistanceCoeff 0.5;    // do not place surface point
                                                // altogether

        // Stop either at maxIterations or if the number of surface pokes
        // is very small (iterationToInitialHitRatioLimit * initial number)
        // Note: perhaps iterationToInitialHitRatioLimit should be absolute
        // count?
        maxIterations 15;

        iterationToInitialHitRatioLimit 0.001;
    }

    // Geometry to mesh to
    geometryToConformTo
    {
        flange.obj
        {
            featureMethod extendedFeatureEdgeMesh; // or none;
            extendedFeatureEdgeMesh "flange.extendedFeatureEdgeMesh";
        }
    }

    // Additional features.
    additionalFeatures
    {
        // line
        //{
        //    featureMethod extendedFeatureEdgeMesh; // or none;
        //    extendedFeatureEdgeMesh "line.extendedFeatureEdgeMesh";
        //}
    }
}


// Controls for seeding initial points and general control of the target
// cell size (used everywhere)
initialPoints
{
    // Do not place point closer than minimumSurfaceDistanceCoeff
    // to the surface. Is fraction of local target cell size (see below)
    minimumSurfaceDistanceCoeff 0.55;

    initialPointsMethod             autoDensity;
    // initialPointsMethod          uniformGrid;
    // initialPointsMethod          bodyCentredCubic;
    // initialPointsMethod          pointFile;


    // Take boundbox of all geometry. Sample with this box. If too much
    // samples in box (due to target cell size) split box.
    autoDensityCoeffs
    {
        // Initial number of refinement levels. Needs to be enough to pick
        // up features due to size ratio. If not enough it will take longer
        // to determine point seeding.
        minLevels 4;
        // Split box if ratio of min to max cell size larger than maxSizeRatio
        maxSizeRatio 5.0;
        // Per box sample 5x5x5 internally
        sampleResolution 5;
        // Additionally per face of the box sample 5x5
        surfaceSampleResolution 5;
    }

    uniformGridCoeffs
    {
        // Absolute cell size.
        initialCellSize         0.0015;
        randomiseInitialGrid    yes;
        randomPerturbationCoeff 0.02;
    }

    bodyCentredCubicCoeffs
    {
        initialCellSize         0.0015;
        randomiseInitialGrid    no;
        randomPerturbationCoeff 0.1;
    }

    pointFileCoeffs
    {
        // Reads points from file. Still rejects points that are too
        // close to the surface (minimumSurfaceDistanceCoeff) or on the
        // wrong side of the surfaces.
        pointFile              "constant/internalDelaunayVertices";
    }
}


// Control size of voronoi cells i.e. distance between points. This
// determines the target cell size which is used everywhere.
// It determines the cell size given a location. It then uses all
// the rules
// - defaultCellSize
// - cellShapeControl
// to determine target cell size. Rule with highest priority wins. If same
// priority smallest cell size wins.
motionControl
{
    // Absolute cell size of back ground mesh. This is the maximum cell size.
    defaultCellSize         0.25;

    minimumCellSizeCoeff    0;

    maxSmoothingIterations  200;

    maxRefinementIterations 2;

    // Calculate the sizes and alignments from surfaces
    shapeControlFunctions
    {
        flange
        {
            type                        searchableSurfaceControl;
            forceInitialPointInsertion  on;
            priority                    1;
            mode                        inside;
            surfaceCellSizeFunction     uniformValue;
            uniformValueCoeffs
            {
                surfaceCellSizeCoeff    0.5;
            }
            cellSizeFunction            surfaceOffsetLinearDistance;
            surfaceOffsetLinearDistanceCoeffs
            {
                distanceCellSizeCoeff   1;
                surfaceOffsetCoeff      1;
                linearDistanceCoeff     1;
            }
        }

        fileControl
        {
            type                    fileControl;
            priority                1;
            pointsFile              "points";
            sizesFile               "sizes";
            alignmentsFile          "alignments";
        }
    }

    // Provide an aspect ratio and the direction in which it acts on the mesh.
    // Default is 1.0 if this section is not present in the dictionary
    cellAspectRatioControl
    {
        // Aspect ratio.
        aspectRatio                 1.0;
        // Direction of action of the aspect ratio
        aspectRatioDirection        (1 0 0);
    }

    // Underrelaxation for point motion. Simulated annealing: starts off at 1
    // and lowers to 0 (at simulation endTime) to converge points.
    // adaptiveLinear is preferred choice.
    // Points move by e.g. 10% of tet size.
    relaxationModel     adaptiveLinear; // rampHoldFall

    adaptiveLinearCoeffs
    {
        relaxationStart 1.0;
        relaxationEnd   0.0;
    }

    // Output lots and lots of .obj files
    objOutput                   no;

    // Timing and memory usage.
    timeChecks                  no;

    // For each delaunay edge (between two vertices, becomes
    // the Voronoi face normal) snap to the alignment direction if within
    // alignmentAcceptanceAngle. Slightly > 45 is a good choice - prevents
    // flipping.
    alignmentAcceptanceAngle    48;

    // When to insert points. Not advisable change to
    // these settings.
    pointInsertionCriteria
    {
        // If edge larger than 1.75 target cell size
        // (so tets too large/stretched) insert point
        cellCentreDistCoeff     1.75;
        // Do not insert point if voronoi face (on edge) very small.
        faceAreaRatioCoeff      0.0025;
        // Insert point only if edge closely aligned to local alignment
        // direction.
        acceptanceAngle         21.5;
    }

    // Opposite: remove point if mesh too compressed. Do not change these
    // settings.
    pointRemovalCriteria
    {
        cellCentreDistCoeff  0.65;
    }

    // How to determine the point motion. All edges got some direction.
    // Sum all edge contributions to determine point motion. Weigh by
    // face area so motion is preferentially determined by large faces
    // (or more importantly ignore contribution from small faces).
    // Do not change these settings.
    faceAreaWeightModel piecewiseLinearRamp;

    piecewiseLinearRampCoeffs
    {
        lowerAreaFraction       0.5;
        upperAreaFraction       1.0;
    }
}


// After simulation, when converting to polyMesh, filter out small faces/edges.
// Do not change. See cvControls.H
polyMeshFiltering
{
    // Filter small edges
    filterEdges                             on;

    // Filter small and sliver faces
    filterFaces                             off;

    // Write the underlying Delaunay tet mesh at output time
    writeTetDualMesh                        false;

    // Upper limit on the size of faces to be filtered.
    // fraction of the local target cell size
    filterSizeCoeff                         0.2;

    // Upper limit on how close two dual vertices can be before
    // being merged, fraction of the local target cell size
    mergeClosenessCoeff                     1e-9;

    // To not filter: set maxNonOrtho to 1 (so check fails) and then
    // set continueFilteringOnBadInitialPolyMesh to false.
    continueFilteringOnBadInitialPolyMesh   true;

    // When a face is "bad", what fraction should the filterSizeCoeff be
    // reduced by.  Recursive, so for a filterCount value of fC, the
    // filterSizeCoeff is reduced by pow(filterErrorReductionCoeff, fC)
    filterErrorReductionCoeff               0.5;

    // Maximum number of filterCount applications before a face
    // is not attempted to be filtered
    filterCountSkipThreshold                4;

    // Maximum number of permissible iterations of the face collapse
    // algorithm.  The value to choose will be related the maximum number
    // of points on a face that is to be collapsed and how many faces
    // around it need to be collapsed.
    maxCollapseIterations                   25;

    // Maximum number of times an to allow an equal faceSet to be
    // returned from the face quality assessment before stopping iterations
    // to break an infinitie loop.
    maxConsecutiveEqualFaceSets             5;
    // Remove little steps (almost perp to surface) by collapsing face.
    surfaceStepFaceAngle                    80;
    // Do not collapse face to edge if should become edges
    edgeCollapseGuardFraction               0.3;
    // Only collapse face to point if high aspect ratio
    maxCollapseFaceToPointSideLengthCoeff   0.35;
}


// Generic mesh quality settings. At any undoable phase these determine
// where to undo. Same as in snappyHexMeshDict
meshQualityControls
{
    //- Maximum non-orthogonality allowed. Set to 180 to disable.
    maxNonOrtho 65;

    //- Max skewness allowed. Set to <0 to disable.
    maxBoundarySkewness 50;
    maxInternalSkewness 10;

    //- Max concaveness allowed. Is angle (in degrees) below which concavity
    //  is allowed. 0 is straight face, <0 would be convex face.
    //  Set to 180 to disable.
    maxConcave 80;

    //- Minimum pyramid volume. Is absolute volume of cell pyramid.
    //  Set to a sensible fraction of the smallest cell volume expected.
    //  Set to very negative number (e.g. -1E30) to disable.
    minVol -1E30;

    //- Minimum quality of the tet formed by the
    //  variable base point minimum decomposition triangles and
    //  the cell centre (so not face-centre decomposition).
    //  This has to be a positive number for tracking
    //  to work. Set to very negative number (e.g. -1E30) to
    //  disable.
    //     <0 = inside out tet,
    //      0 = flat tet
    //      1 = regular tet
    minTetQuality 1e-30;

    //- Minimum absolute face area. Set to <0 to disable.
    minArea -1;

    //- Minimum face twist. Set to <-1 to disable. dot product of face normal
    //  and face centre triangles normal
    minTwist 0.02;

    //- Minimum normalised cell determinant
    //- 1 = hex, <= 0 = folded or flattened illegal cell
    minDeterminant 0.001;

    //- minFaceWeight (0 -> 0.5)
    minFaceWeight 0.02;

    //- minVolRatio (0 -> 1)
    minVolRatio 0.01;

    // must be >0 for Fluent compatibility
    minTriangleTwist -1;
}


// ************************************************************************* //
